package com.cneport.das.common.utils;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author GavinZhang
 * @version 1.0
 * @desc 时间格式化及取相隔距离计算工具
 * @company 东方物通科技有限（北京）公司
 * @date 2021/7/19 18:35
 */

public class DateUtil {
    /**
     * 对象锁
     */
    private static final Object LOCK_OBJ = new Object();

    /**
     * 存放不同的日期模板格式的sdf的Map
     */
    private final static Map<String, ThreadLocal<SimpleDateFormat>> SDF_MAP = new HashMap<String, ThreadLocal<SimpleDateFormat>>();


    /**
     * 返回一个ThreadLocal的sdf,每个线程只会new一次sdf
     *
     * @param pattern
     * @return
     */
    private static SimpleDateFormat getSdf(final String pattern) {
        ThreadLocal<SimpleDateFormat> tl = SDF_MAP.get(pattern);

        // 此处的双重判断和同步是为了防止sdfMap这个单例被多次put重复的sdf
        if (tl == null) {
            synchronized (LOCK_OBJ) {
                tl = SDF_MAP.get(pattern);
                if (tl == null) {
                    // 只有Map中还没有这个pattern的sdf才会生成新的sdf并放入map
                    //log.debug("put new sdf of pattern " + pattern + " to map");

                    // 这里是关键,使用ThreadLocal<SimpleDateFormat>替代原来直接new SimpleDateFormat
                    tl = new ThreadLocal<SimpleDateFormat>() {

                        @Override
                        protected SimpleDateFormat initialValue() {
                            // log.debug("thread: " + Thread.currentThread() + " init pattern: " + pattern);
                            return new SimpleDateFormat(pattern);
                        }
                    };
                    SDF_MAP.put(pattern, tl);
                }
            }
        }

        return tl.get();
    }

    /**
     * 使用ThreadLocal<SimpleDateFormat>来获取SimpleDateFormat,这样每个线程只会有一个SimpleDateFormat
     * 如果新的线程中没有SimpleDateFormat，才会new一个
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date, String pattern) {
        return getSdf(pattern).format(date);
    }

    public static String formatDate(Date date) {
        return getSdf("yyyy-MM-dd").format(date);
    }

    public static String formatTime(Date date) {
        return getSdf("HH:mm:ss").format(date);
    }

    public static Date getDate(Date date) {
        String strDate = formatDate(date);
        return parse(strDate, "yyyy-MM-dd");
    }

    public static Date getTime(Date date) {
        String strDate = formatDate(date);
        return parse(strDate, "HH:mm:ss");
    }

    public static Date parse(String dateStr, String pattern) {
        Date date = null;
        try {
            date = getSdf(pattern).parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    public static DateTime getDateTime(String strDate, String pattern) {
        DateTime dateTime = new DateTime(strDate, pattern);
        return dateTime;
    }

    public static DateTime nowDateTime() {
        DateTime dateTime = new DateTime(new Date());
        return dateTime;
    }

    public static String now() {
        return cn.hutool.core.date.DateUtil.now();
    }

    public static String today() {
        return cn.hutool.core.date.DateUtil.today();
    }

    public static DateTime yesterday() {
        return cn.hutool.core.date.DateUtil.yesterday();
    }

    public static DateTime tomorrow() {
        return cn.hutool.core.date.DateUtil.tomorrow();
    }

    /**
     * 上周的今天是哪一天
     *
     * @return
     */
    public static DateTime lastWeek() {
        return cn.hutool.core.date.DateUtil.lastWeek();
    }

    /**
     * 下周的今天是哪一天
     *
     * @return
     */
    public static DateTime nextWeek() {
        return cn.hutool.core.date.DateUtil.nextWeek();
    }

    /**
     * 距离今天多少年
     *
     * @param date 过去的某一天
     * @return
     */
    public static int ageOfnow(String date) {
        try {
            return cn.hutool.core.date.DateUtil.ageOfNow(parse(date, "yyyy-MM-dd"));
        } catch (Exception e) {
            System.out.println("日期：" + date + "格式不合法！");
        }
        return -1;
    }

    /**
     * 判断是否是运年
     *
     * @param date 如：2017
     * @return
     */
    public static boolean isLeapYear(int date) {
        return cn.hutool.core.date.DateUtil.isLeapYear(date);
    }

    /**
     * 计算偏移多少天的日期
     *
     * @param date 基点日期
     * @param days 偏移天数，正数向后，负数向前。
     * @return
     */
    public static DateTime offsetDays(Date date, int days) {
        return cn.hutool.core.date.DateUtil.offset(date, DateField.DAY_OF_MONTH, days);
    }

    /**
     * 计算偏移多少天的日期
     *
     * @param strDate 基点日期,格式 yyyy-MM-dd,0点开始
     * @param days    偏移天数，正数向后，负数向前。
     * @return
     */
    public static DateTime offsetDays(String strDate, int days) {
        Date date = cn.hutool.core.date.DateUtil.parse(strDate, "yyyy-MM-dd");
        return offsetDays(date, days);
    }

    /**
     * 计算偏移多少天的日期
     *
     * @param date  基点日期 格式 yyyy-MM-dd
     * @param hours 偏移小时数，正数向后，负数向前。
     * @return
     */
    public static DateTime offsetHours(Date date, int hours) {
        return cn.hutool.core.date.DateUtil.offset(date, DateField.HOUR_OF_DAY, hours);
    }

    /**
     * 计算偏移多少天的日期
     *
     * @param strDate 基点日期:格式 yyyy-MM-dd，,0点开始
     * @param hours   偏移小时数，正数向后，负数向前。
     * @return
     */
    public static DateTime offsetHours(String strDate, int hours) {
        Date date = cn.hutool.core.date.DateUtil.parse(strDate, "yyyy-MM-dd");
        return offsetHours(date, hours);
    }

    /**
     * 将DateTime类型转成指定格式的执法串
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String dateTime2Str(DateTime date, String pattern) {
        return date.toString(pattern);
    }

    /**
     * 获得当前时间的年月日时分秒的字符串
     *
     * @return
     */
    public static String C14() {
        return format(new Date(), "yyyyMMddHHmmss");
    }

    /**
     * 获得当前时间的年月日时分秒的字符串
     *
     * @return
     */
    public static String C17() {
        return format(new Date(), "yyyyMMddHHmmssSSS");
    }

    public static String C8() {
        return format(new Date(), "yyyyMMdd");
    }

    public static String C10() {
        return format(new Date(), "yyyyMMddHH");
    }
}
